using System;
using System.Collections.Generic;
using System.IO;
using BepInEx;
using HarmonyLib;
using UnityEngine;


namespace MightPlus
{
    [BepInPlugin("com.menghuan.might.plus", "MightPlus", "2.0.1")]
    public class MightPlus : BaseUnityPlugin
    {
        // 记录所有初始属性的字典
        private static Dictionary<string, HeroInitialStats> initialStatsDict =
            new Dictionary<string, HeroInitialStats>();

        // 记录上一次变更的技能属性 字典
        private static Dictionary<string, StatBonus> lastStatBonusDict = new Dictionary<string, StatBonus>();
        // 声明配置项

        private static float ConfigRangeHeroBaseRange { get; set; }
        private static float ConfigMeleeHeroBaseRange { get; set; }

        private static int ConfigMaxValue { get; set; }

        // 体型放大倍数
        private static float ConfigScaleValue { get; set; }

        // 攻击范围放大倍数
        private static float ConfigRangeMulti { get; set; }

        // 攻击力加成放大倍数
        private static float ConfigAttackMulti { get; set; }

        // 攻击力速度降低倍数
        private static float ConfigAttackSpeedMulti { get; set; }

        // 移速降低倍数
        private static float ConfigMoveSpeedMulti { get; set; }

        // 暴击概率放大倍数
        private static float ConfigCritChanceMulti { get; set; }

        // 暴击伤害放大倍数
        private static float ConfigCritDamageMulti { get; set; }

        // 生命回复放大倍数
        private static float ConfigHealRegenMulti { get; set; }

        //护甲放大倍数
        private static float ConfigArmorMulti { get; set; }

        // 韧性放大倍数
        private static float ConfigTenacityMulti { get; set; }
        private static string ConfigFirstMsg { get; set; }
        private static float ConfigPercentQuality { get; set; }
        private static float ConfigQualityMax { get; set; }

        private void Awake()
        {
            Debug.LogFormat("巨人插件已加载");
        }

        private void Start()
        {
            BindConfig();
            Harmony.CreateAndPatchAll(typeof(MightPlus));
        }

        private void Update()
        {
            // 检测F9按键
            if (!Input.GetKeyDown(KeyCode.F9)) return;
            Config.Reload();
            Debug.Log("重新加载配置");
            var path = Config.ConfigFilePath;
            Logger.LogInfo("=== 文件内容开始 ===");
            Logger.LogInfo(File.ReadAllText(path));
            Logger.LogInfo("=== 文件内容结束 ===");
            BindConfig();
            RefreshStats();
        }

        private static void RefreshStats()
        {
            // 遍历字典中的所有键值对
            foreach (var kvp in initialStatsDict)
            {
                var stats = kvp.Value;
                stats.CurrentHealth -= 1;
            }
        }

        [HarmonyPostfix, HarmonyPatch(typeof(Forest_LoopCat_Spawner), "OnCreate")]
        public static void Forest_LoopCat_Spawner_OnCreate_Patch(Forest_LoopCat_Spawner __instance)
        {
            if (NetworkedManagerBase<ZoneManager>.instance.currentZoneIndex == 0)
            {
                NetworkedManagerBase<ChatManager>.instance.BroadcastChatMessage(new ChatManager.Message
                {
                    type = ChatManager.MessageType.Raw,
                    content = ConfigFirstMsg
                });
            }
        }


        [HarmonyPostfix, HarmonyPatch(typeof(Gem_E_Might), "OnEquipSkill")]
        public static void Gem_E_Might_OnEquipSkill_Patch(Gem_E_Might __instance, SkillTrigger newSkill)
        {
            var hero = __instance.owner;
            var player = hero.owner;
            var playerName = player.playerName + player.GetInstanceID() + PlayGameManager.instance.gameId;
            Debug.Log("playerName" + playerName);

            Debug.Log("装备巨人-ConfigMaxValue:" + ConfigMaxValue);

            if (hero == null && hero.transform == null && ConfigMaxValue < 0)
            {
                return;
            }

            Debug.Log("装备巨人=============");
            // 记录初始属性

            var initialStats = new HeroInitialStats
            {
                BodyScale = hero.transform.localScale,
                AttackRange = hero.Ability.attackAbility.configs[0].castMethod._range,
                CurrentHealth = hero.maxHealth - 1,
            };
            // 打印初始属性
            Debug.Log("装备巨人-初始属性：" + initialStats.ToString());
            // 存入字典
            initialStatsDict[playerName] = initialStats;
        }

        [HarmonyPostfix, HarmonyPatch(typeof(Gem_E_Might), "OnUnequipSkill")]
        public static void Gem_E_Might_OnUnequipSkill_Patch(Gem_E_Might __instance, SkillTrigger oldSkill)
        {
            var hero = __instance.owner;
            if (hero == null || hero.transform == null || ConfigMaxValue < 0)
            {
                return;
            }

            Debug.Log("移除巨人=============");

            var player = hero.owner;
            var playerName = player.playerName + player.GetInstanceID() + PlayGameManager.instance.gameId;
            Debug.Log("playerName" + playerName);

            hero.transform.localScale = initialStatsDict[playerName].BodyScale;
            hero.Ability.attackAbility.configs[0].castMethod._range = initialStatsDict[playerName].AttackRange;

            if (lastStatBonusDict.TryGetValue(playerName, out var bonusLastTemp))
            {
                try
                {
                    hero.Status.RemoveStatBonus(bonusLastTemp);
                }
                catch (Exception e)
                {
                    Debug.Log("抛错了:" + e.Message);
                    lastStatBonusDict.Remove(playerName);
                }
            }

            initialStatsDict.Remove(playerName);
            lastStatBonusDict.Remove(playerName);
        }

        [HarmonyPostfix, HarmonyPatch(typeof(Gem_E_Might), "ActiveLogicUpdate")]
        public static void Gem_E_Might_ActiveLogicUpdate_Patch(Gem_E_Might __instance, float dt)
        {
            var hero = __instance.owner;
            if (hero == null || hero.Status == null || hero.transform == null || ConfigMaxValue < 0)
            {
                return;
            }

            var maxHeal = hero.Status.maxHealth;
            var player = hero.owner;
            var playerName = player.playerName + player.GetInstanceID() + PlayGameManager.instance.gameId;

            if (!initialStatsDict.TryGetValue(playerName, out var heroInitialStatus) ||
                Mathf.Approximately(initialStatsDict[playerName].CurrentHealth, maxHeal))
            {
                return;
            }

            Debug.Log("实时计算=============");
            Debug.Log("playerName=" + playerName);
            var baseIncrease = __instance.currentDamageAmp *
                               Mathf.Min(CalculateProgressiveValue(__instance.quality),
                                   ConfigQualityMax); // 技能基础伤害加成 50生命值提供1%
            Debug.Log("基础加成__instance.currentDamageAmp:" + baseIncrease);
            var bonusNewTemp = new StatBonus
            {
                attackDamageFlat = baseIncrease * 100 * ConfigAttackMulti, // 50生命值提供ConfigAttackMulti点伤害
                attackSpeedPercentage =
                    -baseIncrease * ConfigAttackSpeedMulti, // 50生命值降低1%*ConfigAttackSpeedMulti点攻速速度百分比
                movementSpeedPercentage =-(float)ProcessPercentageGrowth(baseIncrease * ConfigMoveSpeedMulti),
                                          // 50生命值降低1%*ConfigMoveSpeedMulti点移动速度百分比,最多30%
                // critChanceFlat = Mathf.Min(0.99f, baseIncrease * ConfigCritChanceMulti), // 50生命值提供1%*ConfigCritChanceMulti点暴击概率
                critAmpFlat = baseIncrease * ConfigCritDamageMulti, // 50生命值提供10点暴击伤害
                healthRegenFlat = baseIncrease * hero.Status.maxHealth * ConfigHealRegenMulti, // 50生命值提供1%生命回复
                armorFlat = baseIncrease * ConfigArmorMulti * 100, // 50生命值提供ConfigArmorMulti点护甲
                tenacityFlat = baseIncrease * ConfigTenacityMulti, // 50生命值提供1%*ConfigTenacityMulti点韧性
            };
            // 尝试获取上次的属性加成
            if (lastStatBonusDict.TryGetValue(playerName, out var bonusLastTemp))
            {
                try
                {
                    hero.Status.RemoveStatBonus(bonusLastTemp);
                }
                catch (Exception e)
                {
                    Debug.Log("抛错了:" + e.Message);
                    lastStatBonusDict.Remove(playerName);
                }
            }

            hero.Status.AddStatBonus(bonusNewTemp);
            lastStatBonusDict[playerName] = bonusNewTemp;


            // 体型、攻击距离单独处理
            var scaleIncreaseNew = baseIncrease * ConfigScaleValue;
            var rangeIncreaseNew = initialStatsDict[playerName].AttackRange * (1f + baseIncrease * ConfigRangeMulti *
                (hero.IsRangedHero() ? 1 + ConfigRangeHeroBaseRange : 1 + ConfigMeleeHeroBaseRange));
            // 输出攻速加成
            Debug.Log("攻速加成计算结果：" + rangeIncreaseNew);

            // 最大体型限制
            if (ConfigMaxValue != 0 && scaleIncreaseNew > ConfigMaxValue)
            {
                scaleIncreaseNew = ConfigMaxValue;
            }

            Debug.Log("实时计算=装备巨人,体型加成前：" + hero.transform.localScale);
            hero.transform.localScale = (1f + scaleIncreaseNew) * Vector3.one;
            Debug.Log("实时计算-体型加成：" + scaleIncreaseNew + ",体型加成后：" + hero.transform.localScale);

            Debug.Log("实时计算=装备巨人,攻击范围加成前：" + hero.Ability.attackAbility.configs[0].castMethod._range);
            hero.Ability.attackAbility.configs[0].castMethod._range = rangeIncreaseNew;
            Debug.Log("实时计算=装备巨人,攻击范围加成后：" + hero.Ability.attackAbility.configs[0].castMethod._range);

            initialStatsDict[playerName].CurrentHealth = hero.Status.maxHealth;
        }

        // 绑定配置值
        public void BindConfig()
        {
            ConfigMaxValue = Config.Bind<int>(
                "config",
                "maxValue",
                0,
                "最大加成倍数\n防止过大的体型影响游戏体验\n" +
                "0-表示无上限，-1关闭巨人精华增强"
            ).Value;

            ConfigScaleValue = Config.Bind<float>(
                "config",
                "configScaleValue",
                1f,
                "体型倍数：每50生命值提供1%*configScaleValue的体型"
            ).Value;

            ConfigRangeHeroBaseRange = Config.Bind<float>(
                "config",
                "rangeHeroBaseRange",
                1f,
                "远程英雄攻击距离加成倍数：每50生命值提供 1%*rangeMulti*rangeHeroBaseRange的攻击距离 \n"
            ).Value;

            ConfigMeleeHeroBaseRange = Config.Bind<float>(
                "config",
                "meleeHeroBaseRange",
                3f,
                "近战英雄攻击距离加成倍数：每50生命值提供 1%*rangeMulti*meleeHeroBaseRange的攻击距离 \n"
            ).Value;

            ConfigRangeMulti = Config.Bind<float>(
                "config",
                "rangeMulti",
                1f,
                "攻击距离放大倍数:每50生命值提供1%*rangeMulti的基础攻击距离"
            ).Value;

            ConfigAttackMulti = Config.Bind<float>(
                "config",
                "attackMulti",
                5f,
                "攻击力加成放大倍数：每50生命值提供1%*attackMulti的基础攻击力"
            ).Value;

            ConfigAttackSpeedMulti = Config.Bind<float>(
                "config",
                "attackSpeedMulti",
                50f,
                "攻击速度加成放大倍数：每50生命值降低1%*moveSpeedMulti的攻击速度"
            ).Value;

            ConfigMoveSpeedMulti = Config.Bind<float>(
                "config",
                "moveSpeedMulti",
                30f,
                "移动速度加成放大倍数：每50生命值降低1%*moveSpeedMulti的移动速度"
            ).Value;

            ConfigCritChanceMulti = Config.Bind<float>(
                "config",
                "critChanceMulti",
                1f,
                "暴击概率加成放大倍数：每50生命值增加1%*critChanceMulti的暴击概率"
            ).Value;

            ConfigCritDamageMulti = Config.Bind<float>(
                "config",
                "critDamageMulti",
                1f,
                "暴击伤害加成放大倍数：每50生命值增加critDamageMulti的暴击伤害"
            ).Value;

            ConfigHealRegenMulti = Config.Bind<float>(
                "config",
                "healRegenMulti",
                0.015f,
                "生命回复加成放大倍数：每50生命值增加1%*healRegenMulti的最大生命值回复加成"
            ).Value;

            ConfigArmorMulti = Config.Bind<float>(
                "config",
                "armorMulti",
                2f,
                "护甲加成放大倍数：每50生命值增加tenacityMulti的护甲加成"
            ).Value;

            ConfigTenacityMulti = Config.Bind<float>(
                "config",
                "TenacityMulti",
                2f,
                "韧性加成放大倍数：每50生命值增加1%*tenacityMulti的韧性加成"
            ).Value;
            ConfigFirstMsg = Config.Bind<string>(
                "config",
                "firstMsg",
                "<color=#687980>精华增强-巨人精华：</color><color=#af51d8>巨神归来，荣光滔天！生命值提升体型、攻击距离、攻击力、暴击、护甲、生命回复、韧性，降低移速、攻速-by 梦幻</color>\n",
                "打印公告"
            ).Value;
            ConfigPercentQuality = Config.Bind<float>(
                "config",
                "percentQuality",
                500,
                "每50生命提供1%基础加成，根据品质计算基础加成的收益，260%品质，取260，收益 = 品质/percentQuality"
            ).Value;
            ConfigQualityMax = Config.Bind<float>(
                "config",
                "qualityMax",
                99,
                "最大收益，防止过高"
            ).Value;
        }

        private class HeroInitialStats
        {
            public Vector3 BodyScale { get; set; }
            public float AttackRange { get; set; }
            public float CurrentHealth { get; set; }
        }

        /// <summary>
        /// 计算渐进值，根据输入的x值返回对应的进度值
        /// </summary>
        /// <param name="x">输入的数值，用于计算进度</param>
        /// <returns>返回计算后的进度值，范围从0开始逐渐递增</returns>
        private static float CalculateProgressiveValue(float x)
        {
            if (x <= 0) return 0f;

            if (x <= ConfigPercentQuality)
            {
                return x / ConfigPercentQuality;
            }
            else
            {
                // 使用等比数列求和公式: S = a * (1 - r^n) / (1 - r)
                var segments = (int)((x - ConfigPercentQuality) / ConfigPercentQuality);
                var remainder = (x - ConfigPercentQuality) % ConfigPercentQuality;

                // a=1, r=0.5, n=segments
                var sum = (1.0f - Mathf.Pow(0.5f, segments)) / 0.5f;

                // 加上余数部分
                var partial = (remainder / ConfigPercentQuality) * Mathf.Pow(0.5f, segments);

                return 1.0f + sum + partial;
            }
        }

        /// <summary>
        /// 处理百分比增长值，对超出阈值的部分按收益递减规则进行计算
        /// </summary>
        /// <param name="input">输入的百分比增长值</param>
        /// <returns>经过收益递减规则处理后的实际收益值</returns>
        public static double ProcessPercentageGrowth(float input)
        {
            var threshold = 0.2; // 20%阈值

            // 如果小于等于阈值，直接返回
            if (input <= threshold)
            {
                return input;
            }

            // 超出部分按收益递减规则计算
            var excess = input - threshold; // 超出20%的部分

            // 每10%为一个单位
            var units = excess / 0.1; // 转换为10%的单位数

            // 使用等比数列求和公式计算实际收益
            // 首项a=0.1*0.5=0.05，公比r=0.5
            var firstTerm = 0.1 * 0.5;
            var ratio = 0.5;

            // 等比数列求和: S = a * (1 - r^n) / (1 - r)
            var additional = firstTerm * (1.0 - Math.Pow(ratio, units)) / (1.0 - ratio);

            return threshold + additional;
        }

    }
}